package com.baoyouqun.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.cola.dto.Response;
import com.alibaba.cola.dto.SingleResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baoyouqun.base.SystemConstant;
import com.baoyouqun.base.utils.ConvertUtils;
import com.baoyouqun.base.utils.ExcelTool;
import com.baoyouqun.domain.CreateCmd.ReportRecordCreateCmd;
import com.baoyouqun.domain.Enum.HandleStatusEnum;
import com.baoyouqun.domain.Query.ReportRecordQuery;
import com.baoyouqun.domain.Query.ReportRecordQueryBack;
import com.baoyouqun.domain.UpdateCmd.ReportRecordUpdateCmd;
import com.baoyouqun.domain.VO.DemandVO;
import com.baoyouqun.domain.VO.ReportRecordVO;
import com.baoyouqun.domain.VO.ReportWithDemandVO;
import com.baoyouqun.domain.cmd.BatchUpdateReportStatusCmd;
import com.baoyouqun.entity.Demand;
import com.baoyouqun.entity.ReportRecord;
import com.baoyouqun.entity.User;
import com.baoyouqun.mapper.ReportRecordMapper;
import com.baoyouqun.service.DemandService;
import com.baoyouqun.service.ReportRecordService;
import com.baoyouqun.service.UserService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.util.StringUtil;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.io.OutputStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;


@Service
public class ReportRecordServiceImpl extends ServiceImpl<ReportRecordMapper, ReportRecord> implements ReportRecordService {

    @Resource
    private ReportRecordMapper reportRecordMapper;
    @Resource
    private UserService userService;
    @Resource
    private DemandService demandService;

    @Override
    public Map<String, Integer> countValidReportsByUserIds(List<String> userIds) {
        if (CollUtil.isEmpty(userIds)) {
            return Collections.emptyMap();
        }

        // 1. 查询所有有效举报（处理状态为已处理）
        List<ReportRecord> validReports = baseMapper.selectList(new QueryWrapper<ReportRecord>()
                .eq("handle_status", HandleStatusEnum.PROCESSED)  // 处理状态：已处理（2）
                .in("report_target_type", "post", "comment"));  // 只统计帖子/评论的举报

        if (CollUtil.isEmpty(validReports)) {
            return userIds.stream().collect(Collectors.toMap(Function.identity(), k -> 0));
        }

        // 2. 提取被举报对象ID，查询所属用户ID（假设帖子/评论关联到demand表的user_id）
        List<String> targetIds = validReports.stream()
                .map(ReportRecord::getReportTargetId)
                .collect(Collectors.toList());

        // 假设需求表中存储了帖子所属用户ID（根据实际表结构调整）
        Map<String, String> targetOwnerMap = demandService.selectOwnerMapByTargetIds(targetIds);


        // 3. 统计每个用户被举报的次数
        Map<String, Integer> reportCountMap = new HashMap<>();
        for (ReportRecord report : validReports) {
            String targetId = report.getReportTargetId();
            String ownerUserId = targetOwnerMap.get(targetId);
            if (ownerUserId != null && userIds.contains(ownerUserId)) {
                reportCountMap.put(ownerUserId, reportCountMap.getOrDefault(ownerUserId, 0) + 1);
            }
        }

        // 4. 补全所有用户ID（默认0）
        userIds.forEach(userId -> reportCountMap.putIfAbsent(userId, 0));

        return reportCountMap;
    }


    @Override
    public SingleResponse<ReportRecordVO> create(ReportRecordCreateCmd cmd) {
        ReportRecord entity =
                ConvertUtils.copyBean(cmd, ReportRecord.class);
        Boolean result = save(entity);
        if (!result) {
            return SingleResponse.buildFailure("100101", "创建失败");
        }

        ReportRecordVO vo =
                ConvertUtils.copyBean(entity, ReportRecordVO.class);
        return SingleResponse.of(vo);
    }

    @Override
    public Response update(ReportRecordUpdateCmd cmd) {
        if (Objects.isNull(cmd)) {
            return Response.buildFailure("100301", "参数不能为空");
        }
        if (StringUtil.isBlank(cmd.getId())) {
            return Response.buildFailure("100302", "ID不能为空");
        }
        ReportRecord oldEntity = getById(cmd.getId());
        if (Objects.isNull(oldEntity)) {
            return Response.buildFailure("100303", "未查询到此数据");
        }
        oldEntity = ConvertUtils.copyBean(cmd, ReportRecord.class);
        Boolean result = updateById(oldEntity);
        if (result) {
            return Response.buildSuccess();
        } else {
            return Response.buildFailure("100304", "更新失败");
        }
    }

    @Override
    public ReportRecordVO selectById(String id) {
        ReportRecord entity = reportRecordMapper.selectById(id);
        ReportRecordVO vo =
                ConvertUtils.copyBean(entity, ReportRecordVO.class);
        return vo;
    }

    @Override
    public IPage<ReportRecordVO> pageVo(ReportRecordQuery query) {
        IPage<ReportRecord> page = new Page<ReportRecord>(query.getCurrent(), query.getSize());
        page = page(page, new LambdaQueryWrapper<ReportRecord>()
                        .eq(ReportRecord::getUserId, query.getUserId())
//                .eq(Objects.nonNull(query.getHandleStatus()),ReportRecord::getHandleStatus,query.getHandleStatus())
                        .orderByDesc(ReportRecord::getCreateTime)
        );
        Page<ReportRecordVO> voPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
        List<ReportRecordVO> records = ConvertUtils.copyBeanList(page.getRecords(), ReportRecordVO.class);
        if (CollUtil.isNotEmpty(records)) {
            List<String> reportIds = records.stream()
                    .map(ReportRecordVO::getReportTargetId) // 获取举报记录ID
                    .filter(StrUtil::isNotEmpty)
                    .distinct()
                    .collect(Collectors.toList());
            List<Demand> demandVOList = demandService.listByIds(reportIds);
            if (CollUtil.isNotEmpty(demandVOList)) {
                records.forEach(record -> {
                    demandVOList.forEach(demand -> {
                        if (record.getReportTargetId().equals(demand.getId())) {
                            record.setReportTargetTitle(demand.getTitle());
                        }
                    });
                });
            }
        }
        voPage.setRecords(records);

        return voPage;
    }

    // ========================== 后台分页查询（MP纯API，无XML） ==========================
    @Override
    public IPage<ReportWithDemandVO> pageAdminReportWithDemand(ReportRecordQueryBack query) {
        // 1. 参数校验：避免空查询异常（对齐用户示例）
        if (Objects.isNull(query)) {
            query = new ReportRecordQueryBack();
        }

        // 2. 构建分页对象：从query取当前页、每页条数（默认1/10）
        Page<ReportRecord> page = new Page<>(
                Objects.nonNull(query.getCurrent()) ? query.getCurrent() : 1L,
                Objects.nonNull(query.getSize()) ? query.getSize() : 10L
        );

        // 3. 构建筛选条件：复用工具方法，分页+导出共用（核心：举报人姓名→查userIdList）
        LambdaQueryWrapper<ReportRecord> wrapper = buildReportWrapper(query);

        // 4. MP分页查询：仅查举报记录主表（避免多表关联，对齐用户示例）
        page = this.page(page, wrapper);

        // 5. 转换VO+补充关联信息（举报人+帖子）
        List<ReportWithDemandVO> voList = ConvertUtils.copyBeanList(page.getRecords(), ReportWithDemandVO.class);
        // 批量补充举报人信息（避免循环查库）
        takeReporterVO(voList);
        // 批量补充帖子信息（避免循环查库）
        takeDemandVO(voList);

        // 6. 封装分页VO结果：保留总条数、总页数（对齐用户DemandVO分页逻辑）
        Page<ReportWithDemandVO> voPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
        voPage.setRecords(voList);
        return voPage;
    }

    // ========================== 导出Excel（Hutool+POI，完全对齐用户示例） ==========================
    @Override
    public void exportAdminReportExcel(ReportRecordQueryBack query, HttpServletResponse response) {
        // 1. 参数校验：空查询查全部（对齐用户示例）
        if (Objects.isNull(query)) {
            query = new ReportRecordQueryBack();
        }

        try {
            // 2. 查询全量数据：设置超大size避免分页截断（对齐用户示例）
            query.setCurrent(1L);
            query.setSize(Long.MAX_VALUE);
            LambdaQueryWrapper<ReportRecord> wrapper = buildReportWrapper(query);
            List<ReportRecord> reportList = this.list(wrapper);

            // 3. 转换VO+补充关联信息（举报人+帖子）
            List<ReportWithDemandVO> dataList = ConvertUtils.copyBeanList(reportList, ReportWithDemandVO.class);
            takeReporterVO(dataList);
            takeDemandVO(dataList);

            // 4. 无数据校验：抛异常提示前端（对齐用户示例）
            if (CollUtil.isEmpty(dataList)) {
                throw new RuntimeException("无符合条件的举报记录，无法导出");
            }

            // 5. 创建Excel工作簿：XSSF格式支持大量数据（对齐用户示例）
            Workbook workbook = new XSSFWorkbook();
            Sheet sheet = workbook.createSheet("举报记录管理列表");
            sheet.setDefaultColumnWidth(25); // 默认列宽适配长文本

            // 6. 构建表头：与页面展示字段一一对应（对齐用户表头逻辑）
            String[] headers = {
                    "举报ID", "举报类型", "举报内容", "违规截图数", "举报人",
                    "举报时间", "处理状态", "处理人", "处理结果", "处理时间",
                    "被举报帖子标题", "帖子浏览量", "帖子收藏量", "帖子发布人",
                    "帖子紧急程度", "帖子有效期", "帖子状态", "帖子发布时间"
            };
            // 表头样式：字体加粗（对齐用户示例）
            CellStyle headerStyle = workbook.createCellStyle();
            Font headerFont = workbook.createFont();
            headerFont.setBold(true);
            headerStyle.setFont(headerFont);
            // 写入表头（第0行）
            Row headerRow = sheet.createRow(0);
            for (int i = 0; i < headers.length; i++) {
                Cell cell = headerRow.createCell(i);
                cell.setCellValue(headers[i]);
                cell.setCellStyle(headerStyle);
            }

            // 7. 填充数据行：逐行处理，避免空指针（对齐用户数据处理逻辑）
            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
            for (int i = 0; i < dataList.size(); i++) {
                ReportWithDemandVO vo = dataList.get(i);
                Row dataRow = sheet.createRow(i + 1); // 从第1行开始（表头占0行）

                // 举报ID
                dataRow.createCell(0).setCellValue(StrUtil.blankToDefault(vo.getId(), ""));
                // 举报类型：枚举中文描述（对齐用户枚举处理）
                String reportTypeDesc = Objects.nonNull(vo.getReportType()) ? vo.getReportType().getDesc() : "";
                dataRow.createCell(1).setCellValue(reportTypeDesc);
                // 举报内容：截取前100字避免单元格过长
                String content = StrUtil.blankToDefault(vo.getReportContent(), "");
                dataRow.createCell(2).setCellValue(StrUtil.sub(content, 0, 100));
                // 违规截图数：列表长度（Hutool CollUtil）
                int fileCount = CollUtil.isNotEmpty(vo.getFiles()) ? vo.getFiles().size() : 0;
                dataRow.createCell(3).setCellValue(fileCount);
                // 举报人姓名
                dataRow.createCell(4).setCellValue(StrUtil.blankToDefault(vo.getReporterName(), "未知用户"));
                // 举报时间：格式化（对齐用户时间处理）
                String reportTime = Objects.nonNull(vo.getCreateTime()) ? vo.getCreateTime().format(dtf) : "";
                dataRow.createCell(5).setCellValue(reportTime);
                // 处理状态：枚举中文描述
                String handleStatusDesc = Objects.nonNull(vo.getHandleStatus()) ? vo.getHandleStatus().getDesc() : "未处理";
                dataRow.createCell(6).setCellValue(handleStatusDesc);
                // 处理人：暂用ID（实际可关联管理员表查姓名）
                dataRow.createCell(7).setCellValue(StrUtil.blankToDefault(vo.getHandlerUserId(), "未处理"));
                // 处理结果
                dataRow.createCell(8).setCellValue(StrUtil.blankToDefault(vo.getHandleResult(), "未处理"));
                // 处理时间
                String handleTime = Objects.nonNull(vo.getHandleTime()) ? vo.getHandleTime().format(dtf) : "";
                dataRow.createCell(9).setCellValue(handleTime);
                // 被举报帖子标题
                dataRow.createCell(10).setCellValue(StrUtil.blankToDefault(vo.getDemandTitle(), "帖子已删除"));
                // 帖子浏览量：默认0（对齐用户数值处理）
                int viewCount = Objects.nonNull(vo.getDemandViewCount()) ? vo.getDemandViewCount() : 0;
                dataRow.createCell(11).setCellValue(viewCount);
                // 帖子收藏量：默认0
                int collectCount = Objects.nonNull(vo.getDemandCollectCount()) ? vo.getDemandCollectCount() : 0;
                dataRow.createCell(12).setCellValue(collectCount);
                // 帖子发布人
                dataRow.createCell(13).setCellValue(StrUtil.blankToDefault(vo.getDemandPublisherName(), "未知发布人"));
                // 帖子紧急程度
                dataRow.createCell(14).setCellValue(StrUtil.blankToDefault(vo.getDemandUrgencyDesc(), ""));
                // 帖子有效期
                dataRow.createCell(15).setCellValue(StrUtil.blankToDefault(vo.getDemandValidityDesc(), ""));
                // 帖子状态：中文描述（对齐用户getStatusDesc逻辑）
                String demandStatusDesc = getDemandStatusDesc(vo.getDemandStatus());
                dataRow.createCell(16).setCellValue(demandStatusDesc);
                // 帖子发布时间
                String demandCreateTime = Objects.nonNull(vo.getDemandCreateTime()) ? vo.getDemandCreateTime().format(dtf) : "";
                dataRow.createCell(17).setCellValue(demandCreateTime);
            }

            // 8. 设置响应头：解决中文文件名乱码（完全对齐用户示例）
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            String fileName = "举报记录列表_" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) + ".xlsx";
            response.setCharacterEncoding("UTF-8");
            response.setHeader("Pragma", "public");
            response.setHeader("Cache-Control", "max-age=30");
            ExcelTool.setExportFileName(response, fileName);

            // 9. 输出Excel流：try-with-resources自动关流（对齐用户示例）
            try (OutputStream outputStream = response.getOutputStream()) {
                workbook.write(outputStream);
                outputStream.flush();
            } finally {
                workbook.close(); // 手动关工作簿，释放POI资源
            }

        } catch (IOException e) {
            log.error("导出举报记录Excel：IO异常", e);
            throw new RuntimeException("导出Excel失败：" + e.getMessage());
        } catch (Exception e) {
            log.error("导出举报记录Excel：未知异常", e);
            throw new RuntimeException("导出Excel异常：" + e.getMessage());
        }
    }

    // ========================== 批量设置违规（事务+MP API） ==========================
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Response batchSetViolation(BatchUpdateReportStatusCmd cmd) {
        // 1. 参数校验（对齐用户示例）
        if (Objects.isNull(cmd) || CollUtil.isEmpty(cmd.getReportIds())) {
            return Response.buildFailure("100301", "举报记录ID列表不能为空");
        }
        if (StrUtil.isBlank(cmd.getHandlerUserId())) {
            return Response.buildFailure("100301", "处理人ID不能为空");
        }

        // 2. MP查询待处理举报记录（对齐用户listByIds逻辑）
        List<ReportRecord> reportList = this.listByIds(cmd.getReportIds());
        if (CollUtil.isEmpty(reportList)) {
            return Response.buildFailure("100303", "未查询到任何举报记录");
        }

        // 3. 提取有效帖子ID（仅处理举报类型为demand的记录）
        List<String> demandIds = reportList.stream()
                .filter(report -> "post".equals(report.getReportTargetType()))
                .map(ReportRecord::getReportTargetId)
                .distinct()
                .collect(Collectors.toList());

        // 4. 批量更新举报记录：状态=已违规（HandleStatusEnum.PROCESSED=2）
        LocalDateTime now = LocalDateTime.now();
        List<ReportRecord> updateReports = reportList.stream().map(report -> {
            report.setHandleStatus(HandleStatusEnum.PROCESSED);
            report.setHandlerUserId(cmd.getHandlerUserId());
            report.setHandleTime(now);
            report.setHandleResult(StrUtil.blankToDefault(cmd.getHandleResult(), "已判定违规，帖子已下架"));
            report.setUpdateTime(now);
            return report;
        }).collect(Collectors.toList());
        boolean reportUpdate = this.updateBatchById(updateReports); // MP批量更新
        if (!reportUpdate) {
            throw new RuntimeException("举报记录批量更新失败");
        }

        // 5. 批量更新帖子：状态=下架（status=-1，对齐用户Demand状态逻辑）
        if (CollUtil.isNotEmpty(demandIds)) {
            List<Demand> updateDemands = demandIds.stream().map(id -> {
                Demand demand = new Demand();
                demand.setId(id);
                demand.setStatus((byte) -1);
                demand.setStatusByBack(true);
                return demand;
            }).collect(Collectors.toList());
            boolean demandUpdate = demandService.updateBatchById(updateDemands); // MP批量更新
            if (!demandUpdate) {
                throw new RuntimeException("帖子状态批量更新失败");
            }
        }

        return Response.buildSuccess();
    }

    // ========================== 批量设置正常（与违规逻辑对称） ==========================
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Response batchSetNormal(BatchUpdateReportStatusCmd cmd) {
        // 1. 参数校验（同违规接口）
        if (Objects.isNull(cmd) || CollUtil.isEmpty(cmd.getReportIds())) {
            return Response.buildFailure("100301", "举报记录ID列表不能为空");
        }
        if (StrUtil.isBlank(cmd.getHandlerUserId())) {
            return Response.buildFailure("100301", "处理人ID不能为空");
        }

        // 2. MP查询待处理举报记录
        List<ReportRecord> reportList = this.listByIds(cmd.getReportIds());
        if (CollUtil.isEmpty(reportList)) {
            return Response.buildFailure("100303", "未查询到任何举报记录");
        }

        // 3. 提取有效帖子ID
        List<String> demandIds = reportList.stream()
                .filter(report -> "post".equals(report.getReportTargetType()))
                .map(ReportRecord::getReportTargetId)
                .distinct()
                .collect(Collectors.toList());

        // 4. 批量更新举报记录：状态=已驳回（HandleStatusEnum.REJECTED=3）
        LocalDateTime now = LocalDateTime.now();
        List<ReportRecord> updateReports = reportList.stream().map(report -> {
            report.setHandleStatus(HandleStatusEnum.REJECTED);
            report.setHandlerUserId(cmd.getHandlerUserId());
            report.setHandleTime(now);
            report.setHandleResult(StrUtil.blankToDefault(cmd.getHandleResult(), "判定无违规，帖子已恢复正常"));
            report.setUpdateTime(now);
            return report;
        }).collect(Collectors.toList());
        boolean reportUpdate = this.updateBatchById(updateReports);
        if (!reportUpdate) {
            throw new RuntimeException("举报记录批量更新失败");
        }

        // 5. 批量更新帖子：状态=正常（status=1）
        if (CollUtil.isNotEmpty(demandIds)) {
            List<Demand> updateDemands = demandIds.stream().map(id -> {
                Demand demand = new Demand();
                demand.setId(id);
                demand.setStatus((byte) 1);
                return demand;
            }).collect(Collectors.toList());
            boolean demandUpdate = demandService.updateBatchById(updateDemands);
            if (!demandUpdate) {
                throw new RuntimeException("帖子状态批量更新失败");
            }
        }

        return Response.buildSuccess();
    }

    // ========================== 批量查询举报关联帖子（用于展开/收起） ==========================
    @Override
    public List<ReportWithDemandVO> listReportWithDemand(List<String> reportIds) {
        // 1. 参数校验
        if (CollUtil.isEmpty(reportIds)) {
            return new ArrayList<>();
        }

        // 2. MP查询举报记录
        List<ReportRecord> reportList = this.listByIds(reportIds);
        if (CollUtil.isEmpty(reportList)) {
            return new ArrayList<>();
        }

        // 3. 转换VO+补充关联信息
        List<ReportWithDemandVO> voList = ConvertUtils.copyBeanList(reportList, ReportWithDemandVO.class);
        takeReporterVO(voList);
        takeDemandVO(voList);
        return voList;
    }

    // ========================== 工具方法（复用逻辑，对齐用户示例） ==========================

    /**
     * 构建举报记录筛选条件（分页+导出共用，核心：举报人姓名→查userIdList）
     *
     * @param query 筛选条件
     * @return MP LambdaQueryWrapper
     */
    private LambdaQueryWrapper<ReportRecord> buildReportWrapper(ReportRecordQueryBack query) {
        LambdaQueryWrapper<ReportRecord> wrapper = new LambdaQueryWrapper<>();

        // 1. 举报类型筛选：枚举匹配
        wrapper.eq(Objects.nonNull(query.getReportType()), ReportRecord::getReportType, query.getReportType());

        // 2. 处理状态筛选：枚举匹配
        wrapper.eq(Objects.nonNull(query.getHandleStatus()), ReportRecord::getHandleStatus, query.getHandleStatus());

        // 3. 举报人姓名筛选：先查userIdList→IN查询（核心需求，对齐用户publisherName处理）
        if (StrUtil.isNotBlank(query.getReporterName())) {
            // 调用UserService模糊查询用户ID列表（避免循环查库）
            List<String> userIdList = userService.listUserIdsByName("%" + query.getReporterName() + "%");
            // 无匹配用户时，加无效条件避免全表扫描（对齐用户逻辑）
            if (CollUtil.isEmpty(userIdList)) {
                wrapper.eq(ReportRecord::getUserId, StrUtil.EMPTY);
            } else {
                wrapper.in(ReportRecord::getUserId, userIdList);
            }
        }

        // 4. 举报时间范围筛选
        wrapper.ge(Objects.nonNull(query.getCreateTimeStart()), ReportRecord::getCreateTime, query.getCreateTimeStart())
                .le(Objects.nonNull(query.getCreateTimeEnd()), ReportRecord::getCreateTime, query.getCreateTimeEnd());

        // 6. 默认排序：按举报时间倒序（最新在前）
        wrapper.orderByDesc(ReportRecord::getCreateTime);

        return wrapper;
    }

    /**
     * 批量补充举报人信息（对齐用户takeUserVO方法，避免循环查库）
     *
     * @param voList 举报VO列表
     */
    private void takeReporterVO(List<ReportWithDemandVO> voList) {
        if (CollUtil.isEmpty(voList)) {
            return;
        }

        // 1. 提取所有举报人ID（去重）
        List<String> userIds = voList.stream()
                .map(ReportWithDemandVO::getUserId)
                .filter(StrUtil::isNotEmpty)
                .distinct()
                .collect(Collectors.toList());
        if (CollUtil.isEmpty(userIds)) {
            return;
        }

        // 2. MP批量查询用户（一次查库）
        List<User> userList = userService.listByIds(userIds);
        Map<String, User> userMap = userList.stream()
                .collect(Collectors.toMap(User::getId, user -> user, (k1, k2) -> k1));

        // 3. 填充举报人信息（默认值：未知用户/默认头像）
        for (ReportWithDemandVO vo : voList) {
            User user = userMap.getOrDefault(vo.getUserId(), null);
            if (Objects.nonNull(user)) {
                vo.setReporterName(user.getName());
                vo.setReporterHeadImg(user.getHeadImg());
            } else {
                vo.setReporterName(SystemConstant.DEFAULT_NAME); // 如："未知用户"
                vo.setReporterHeadImg(SystemConstant.DEFAULT_HEAD_IMG); // 如：默认头像URL
            }
        }
    }

    /**
     * 批量补充被举报帖子信息（优化：循环查询改为一次性查询+匹配）
     *
     * @param voList 举报VO列表
     */
    private void takeDemandVO(List<ReportWithDemandVO> voList) {
        if (CollUtil.isEmpty(voList)) {
            return;
        }

        // 1. 提取所有举报记录ID（去重），用于批量查询ReportRecord
        List<String> reportIds = voList.stream()
                .map(ReportWithDemandVO::getId) // 获取举报记录ID
                .filter(StrUtil::isNotEmpty)
                .distinct()
                .collect(Collectors.toList());
        if (CollUtil.isEmpty(reportIds)) {
            return;
        }

        // 2. 一次性批量查询所有举报记录（替代循环getById，仅1次数据库查询）
        List<ReportRecord> reportRecords = this.listByIds(reportIds);
        Map<String, ReportRecord> reportMap = reportRecords.stream()
                .collect(Collectors.toMap(ReportRecord::getId, report -> report, (k1, k2) -> k1)); // 用举报ID作为key

        // 3. 提取所有帖子ID（从批量查询的ReportRecord中获取，避免循环查库）
        List<String> demandIds = voList.stream()
                .map(vo -> {
                    ReportRecord reportRecord = reportMap.get(vo.getId()); // 从map中直接获取，无数据库查询
                    return Objects.nonNull(reportRecord) ? reportRecord.getReportTargetId() : StrUtil.EMPTY;
                })
                .filter(StrUtil::isNotEmpty)
                .distinct()
                .collect(Collectors.toList());
        if (CollUtil.isEmpty(demandIds)) {
            return;
        }

        // 4. 批量查询帖子信息（一次查库）
        List<Demand> list = demandService.listByIds(demandIds);
        List<DemandVO> demandList = ConvertUtils.copyBeanList(list, DemandVO.class);
        demandService.takeUserVO(demandList);
        Map<String, DemandVO> demandMap = demandList.stream()
                .collect(Collectors.toMap(DemandVO::getId, demand -> demand, (k1, k2) -> k1));

        // 5. 填充帖子信息（从map中匹配，无数据库查询）
        for (ReportWithDemandVO vo : voList) {
            // 从批量查询的map中获取举报记录，避免循环查库
            ReportRecord reportRecord = reportMap.get(vo.getId());
            String demandId = Objects.nonNull(reportRecord) ? reportRecord.getReportTargetId() : StrUtil.EMPTY;
            DemandVO demand = demandMap.getOrDefault(demandId, null);

            if (Objects.nonNull(demand)) {
                vo.setDemandId(demand.getId());
                vo.setDemandTitle(demand.getTitle());
                vo.setDemandDescription(demand.getDescription());
                vo.setDemandViewCount(demand.getViewCount());
                vo.setDemandCollectCount(demand.getCollectCount());
                vo.setDemandDislikeCount(demand.getDislikeCount());
                vo.setDemandCreateTime(demand.getCreateTime());
                vo.setDemandStatus(demand.getStatus());
                vo.setDemandPublisherName(Objects.nonNull(demand.getUserSimpleVO()) ? demand.getUserSimpleVO().getName() : "未知发布人");
                vo.setDemandUrgencyDesc(Objects.nonNull(demand.getResourceUrgency()) ? demand.getResourceUrgency().getName() : "");
                String validityDesc = Boolean.TRUE.equals(demand.getNeverExpire())
                        ? "资源长期有效"
                        : (Objects.nonNull(demand.getExpireTime())
                        ? demand.getExpireTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"))
                        : "未设置");
                vo.setDemandValidityDesc(validityDesc);
            } else {
                vo.setDemandTitle("帖子已删除");
                vo.setDemandPublisherName("未知发布人");
            }
        }
    }

    /**
     * 帖子状态中文描述（对齐用户getStatusDesc方法）
     *
     * @param status 帖子状态（-1=下架，0=隐藏，1=正常，2=删除）
     * @return 中文描述
     */
    private String getDemandStatusDesc(Byte status) {
        return switch (Objects.requireNonNullElse(status, (byte) 0)) {
            case -1 -> "已下架";
            case 0 -> "已隐藏";
            case 1 -> "正常";
            case 2 -> "已删除";
            default -> "未知状态";
        };
    }
}